/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.controller;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import lombok.extern.slf4j.Slf4j;
import org.springblade.common.constant.TemplateMsgConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.NoticeRemoveDTO;
import org.springblade.modules.admin.dto.UserNoticeDTO;
import org.springblade.modules.admin.service.WeChatDialogueService;
import org.springblade.modules.admin.utils.AsyncUtils;
import org.springblade.modules.admin.vo.NoticeTypeVO;
import org.springblade.modules.admin.vo.UserNoticeListVO;
import org.springblade.modules.desk.entity.Notice;
import org.springblade.modules.desk.service.INoticeService;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.admin.entity.UserNotice;
import org.springblade.modules.admin.service.IUserNoticeService;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.modules.admin.dto.UserNoticeListDTO;

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 用户通知表 控制器
 *
 * @author ysq
 * @since 2024-04-01
 */
@RestController
@AllArgsConstructor
@RequestMapping("sida-maintain-admin/user-notice")
@Api(value = "用户通知表", tags = "用户通知表接口")
@Slf4j
public class UserNoticeController extends BladeController {

	private final IUserNoticeService userNoticeService;

	private final IUserService userService;

	private final INoticeService noticeService;

	private final WeChatDialogueService weChatDialogueService;

	private final AsyncUtils asyncUtils;

	/**
	 * 新增/重新发布通知
	 * @param userNoticeDTO 用户通知表
	 * @return 新增结果
	 */
	@PostMapping("/addNotice")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "新增通知", notes = "新增通知")
	public R<Boolean> addNotice(@RequestBody UserNoticeDTO userNoticeDTO) {
		// 1. 参数校验，由于复用的关系舍弃@Valid注解，直接在service层进行参数校验
		List<Long> userIds = userNoticeDTO.getUserIds();
		if(Func.isEmpty(userIds)){
			throw new ServiceException("业务异常，请选择推送对象\n Exception: please select push objects");
		}
		String title = userNoticeDTO.getTitle();
		if(Func.isNull(title) || Func.isBlank(title)){
			throw new ServiceException("业务异常，请输入通知标题\n Exception: please fill in the notice title");
		}
		String content = userNoticeDTO.getContent();
		if(Func.isNull(content) || Func.isBlank(content)){
			throw new ServiceException("业务异常，请输入通知内容\n Exception: please fill in the notice content");
		}
		Integer category = userNoticeDTO.getCategory();
		if(Func.isNull(category) || category < 0){
			throw new ServiceException("业务异常，请选择通知类型或通知类型值不正确\n Exception: please select notice type");
		}
		// 2. 新增通知、新增用户关联关系, 通知用户一对多关系
		Notice notice = new Notice();
		notice.setTitle(title);
		notice.setContent(content);
		notice.setCategory(category);
		boolean isSave = noticeService.save(notice);
		if(isSave){

			List<UserNotice> userNotices = new ArrayList<>();
			for(Long userId : userIds){
				UserNotice userNotice = new UserNotice();
				userNotice.setUserId(userId);
				userNotice.setNoticeId(notice.getId());
				userNotices.add(userNotice);
			}
			isSave = userNoticeService.saveBatch(userNotices);
		}
		Long sendUserId = AuthUtil.getUserId();
		User sendUser = userService.getById(sendUserId);
		String sendName = sendUser.getRealName();
		// 3. 发送微信通知
		if(isSave) {
			log.info("============= 发送微信通知 =============");
			Long noticeId = notice.getId();
			for (Long userId : userIds) {
				SimpleUserVO assignUserInfo = userService.getSimpleUserInfo(userId);
				if (Func.isNotEmpty(assignUserInfo)) {
					if(Func.isNotEmpty(assignUserInfo.getOpenid())){
						String skipUrl = "pages/notice/detail?id="+noticeId;
						Map<String, String> templateDataMap = new HashMap<>(8);
//						templateDataMap.put("first", "员工服务系统审批通知");
						// 发送人
						templateDataMap.put("thing2", sendName);
						templateDataMap.put("time3", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
						templateDataMap.put("thing4", title);
//						templateDataMap.put("remark", "请及时登录梯无忧小程序查看通知!");
						templateDataMap.put("params", skipUrl);
						log.info("发送微信通知，用户：{}, 通知：{}", assignUserInfo.getOpenid(), templateDataMap);
						asyncUtils.sendWeiXinTemplate(assignUserInfo.getOpenid(),TemplateMsgConstant.NOTICE_MESSAGE,templateDataMap);
					}
				}
			}
		}
		return R.data(isSave);
	}

	/**
	 * 删除 通知、用户关联关系
	 * @param noticeRemoveDTO 主键id集合
	 * @return 删除结果
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 20)
	@ApiOperation(value = "逻辑删除通知", notes = "传入ids")
	public R<Boolean> remove(@RequestBody NoticeRemoveDTO noticeRemoveDTO ) {
		List<String> ids = noticeRemoveDTO.getIds();
		// 1. 数据校验，ids 是否为空
		if(Func.isEmpty(ids)){
			throw new ServiceException("业务异常，请选择需要删除的通知\n Exception: please select the notice to delete");
		}
		// 将 ids 转换为 Long 集合
		List<Long> idList = new ArrayList<>();
		for(String id : ids){
			idList.add(Long.parseLong(id));
		}
		boolean isSuccess = noticeService.removeByIds(idList);
		if(isSuccess){
			List<UserNotice> userNoticesList = userNoticeService.list(
				new LambdaQueryWrapper<UserNotice>()
					.in(UserNotice::getNoticeId, idList)
			);
			isSuccess = userNoticeService.removeByIds(
				userNoticesList.stream()
					.map(UserNotice::getId)
					.collect(ArrayList::new, ArrayList::add, ArrayList::addAll)
			);
		}
		return R.data(isSuccess);
	}

	/**
	 * 自定义分页 用户通知表
	 */
	@PostMapping("/page")
	@ApiOperationSupport(order = 30)
	@ApiOperation(value = "分页", notes = "传入userNotice")
	public R<IPage<UserNoticeListVO>> page(@RequestBody UserNoticeListDTO userNoticeListDTO) {
		Query query = userNoticeListDTO.getQuery();
		IPage<UserNoticeListVO> pages = userNoticeService.pageByCondition(Condition.getPage(query), userNoticeListDTO);
		return R.data(pages);
	}

	/**
	 * 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 31)
	@ApiOperation(value = "详情", notes = "传入userNotice")
	public R<UserNoticeListVO> detail(Long noticeId) {
		UserNoticeListVO userNoticeListVO = userNoticeService.getDetailById(noticeId);
		return R.data(userNoticeListVO);
	}

	/**
	 * 通知类型下拉列表，具体类型对应字典表 blade_dict code = 'notice'
	 * @return 通知类型下拉列表
	 */
	@GetMapping("/noticeType/list")
	@ApiOperationSupport(order = 32)
	@ApiOperation(value = "通知类型下拉列表", notes = "通知类型下拉列表")
	public R<List<NoticeTypeVO>> noticeType() {
		return R.data(userNoticeService.getNoticeType());
	}

}
